package org.pupil.socket.client;


import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.pupil.common.constants.MsgType;
import org.pupil.common.constants.ProtocolConstants;
import org.pupil.common.constants.RpcSerialization;
import org.pupil.socket.codec.MsgHeader;
import org.pupil.socket.codec.RpcDecoder;
import org.pupil.socket.codec.RpcEncoder;
import org.pupil.socket.codec.RpcProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Description: 服务发送方
 * @Author: pupil
 * @Date: 2024/07/06 下午 9:43
 */
public class Client {
    private Logger logger = LoggerFactory.getLogger(Client.class);

    private final String host; // 服务提供方的主机名或ip地址
    private final Integer port; // 服务提供方的端口号

    private final Bootstrap bootstrap;
    private final EventLoopGroup eventLoopGroup;

    private ChannelFuture channelFuture;

    public Client(String hostName, int port) throws InterruptedException {
        this.host = hostName;
        this.port = port;

        bootstrap = new Bootstrap();
        eventLoopGroup = new NioEventLoopGroup(4);

        bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)
                .option(ChannelOption.SO_KEEPALIVE, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline()
                                .addLast(new RpcEncoder())
                                .addLast(new RpcDecoder());
                    }
                });
        channelFuture = bootstrap.connect(hostName, port).sync();
    }

    // 发送请求
    public void sendRequest(Object o) {
        channelFuture.channel().writeAndFlush(o);
    }

    public static void main(String[] args) throws InterruptedException {
        Client client = new Client("127.0.0.1", 8081);

        // 构建消息头
        MsgHeader msgHeader = new MsgHeader();
        msgHeader.setMagic(ProtocolConstants.MAGIC);
        msgHeader.setVersion(ProtocolConstants.VERSION);
        msgHeader.setMsgType((byte) MsgType.REQUEST.ordinal());
        msgHeader.setStatus((byte) 0x1);
        long requestId = 123;
        msgHeader.setRequestId(requestId);
        byte[] serializations = RpcSerialization.JSON.name.getBytes();
        msgHeader.setSerializationLen(serializations.length);
        msgHeader.setSerializations(serializations);

        // 构建消息
        RpcProtocol<MyObject> rpcProtocol = new RpcProtocol<>();
        rpcProtocol.setMsgHeader(msgHeader);
        rpcProtocol.setBody(new MyObject());

        // 发送请求
        client.sendRequest(rpcProtocol);
    }

}

class Address {
    private String host = "127.0.0.1";

    private int port = 8080;

    public Address() {
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    @Override
    public String toString() {
        return "Address{" +
                "host='" + host + '\'' +
                ", port=" + port +
                '}';
    }
}


class MyObject {
    private static final long serialVersionUID = 1L; //用于确保序列化和反序列化过程中类的一致性

    private String name = "pupil";

    private Integer age = 21;

    private Address address = new Address();


    public MyObject() {
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "MyObject{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", address=" + address +
                '}';
    }

}
